package com.ccys.netty.handler;



import com.alibaba.fastjson.JSONObject;
import com.ccys.common.util.StringUtil;
import com.ccys.netty.config.NettyConfig;
import com.ccys.netty.util.SpringUtil;
import io.netty.channel.*;
import io.netty.handler.codec.http.FullHttpRequest;
import io.netty.handler.timeout.IdleState;
import io.netty.handler.timeout.IdleStateEvent;
import io.netty.util.AttributeKey;
import io.netty.util.CharsetUtil;
import lombok.extern.slf4j.Slf4j;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;

@ChannelHandler.Sharable
@Slf4j
public class CustomHandler extends ChannelInboundHandlerAdapter {

    public static Map<String,ChannelHandlerContext> CHANNEL_MAP = new ConcurrentHashMap();

    public static AtomicInteger nConnection = new AtomicInteger();

    @Override
    public void channelRegistered(ChannelHandlerContext ctx)  {
        log.info("========客户端注册=======");
    }

    @Override
    public void channelUnregistered(ChannelHandlerContext ctx)  {
        log.info("========客户端注销=======");
    }

    @Override
    public void channelActive(ChannelHandlerContext ctx)  {
        log.info("========客户端连接=======");
        nConnection.incrementAndGet();

        JSONObject jsonObject = new JSONObject();
        jsonObject.put("channelId",ctx.channel().id().asLongText());
        jsonObject.put("state","success");
        jsonObject.put("userId", "666666");
        ctx.channel().writeAndFlush("收到客户端连接时回复消息：" + jsonObject.toJSONString());
        log.info("========当前连接数:{}",nConnection.get());

        CHANNEL_MAP.put(jsonObject.getString("channelId"),ctx);
    }

    @Override
    public void channelInactive(ChannelHandlerContext ctx)  {
        log.info("========客户端断开=======");
        nConnection.decrementAndGet();
    }
    /**
     * 一旦连接，第一个被执行
     * @param ctx
     * @throws Exception
     */
    @Override
    public void handlerAdded(ChannelHandlerContext ctx)   {
        log.info("handlerAdded 被调用"+ctx.channel().id().asLongText());
        // 添加到channelGroup 通道组
        NettyConfig.getChannelGroup().add(ctx.channel());
    }
    @Override
    public void handlerRemoved(ChannelHandlerContext ctx) throws Exception {
        log.info("handlerRemoved 被调用"+ctx.channel().id().asLongText());
        // 删除通道
        NettyConfig.getChannelGroup().remove(ctx.channel());
        removeUserId(ctx);
    }
    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg)  {
        log.info("=========读取消息==========");
        log.info("读取消息为:{}",msg);
        if(msg instanceof FullHttpRequest){
            //Android  app端 测试使用的是这种方式
            FullHttpRequest data = (FullHttpRequest) msg;
            String uri = data.uri();
            System.out.println("uri = " + uri);
            JSONObject jsonObject = null;
            if(StringUtil.isNotEmpty(uri)) {
                String param = uri.substring(uri.indexOf("?") + 1);
                jsonObject = WebSocketFrameHandler.splitString(param);

            }
            System.out.println("消息对象转字符串= " + data.toString());
            if("heart".equals(data)){
                //心跳 app端有连接失败自动重连机制

            }
            if(jsonObject != null) {
                // 获取用户ID
                String bookingId = jsonObject.getString("booking_id");
                // 将用户ID作为自定义属性加入到channel中，方便随时channel中获取用户ID
                AttributeKey<String> key = AttributeKey.valueOf("bookingId");
                ctx.channel().attr(key).setIfAbsent(bookingId);
                // 关联channel
                NettyConfig.getUserChannelMap().put(bookingId,ctx);
            }



        }else if(msg instanceof String){
            String data = (String) msg;
            String substring = data.substring(data.indexOf("?") + 1, data.indexOf(" HTTP/1.1"));
            JSONObject jsonObject = null;
            if(StringUtil.isNotEmpty(substring)) {
                jsonObject = WebSocketFrameHandler.splitString(substring);
            }
            if(jsonObject != null) {
                // 获取用户ID
                String bookingId = jsonObject.getString("booking_id");
                // 将用户ID作为自定义属性加入到channel中，方便随时channel中获取用户ID
                AttributeKey<String> key = AttributeKey.valueOf("bookingId");
                ctx.channel().attr(key).setIfAbsent(bookingId);
                // 关联channel
                NettyConfig.getUserChannelMap().put(bookingId,ctx);
            }
        }
        ctx.channel().writeAndFlush("服务端收到消息后自动回复消息：hello word " + msg);


    }

    @Override
    public void channelReadComplete(ChannelHandlerContext ctx)  {
        log.info("========消息读取完毕=======");
    }

    @Override
    public void userEventTriggered(ChannelHandlerContext ctx, Object evt)  {
        log.info("========触发事件=======");
        if(evt instanceof IdleStateEvent){
            //服务端对应着读事件，当为READER_IDLE时触发
            IdleStateEvent event = (IdleStateEvent)evt;
            if(event.state() == IdleState.READER_IDLE){
                log.info("关闭不活动的链接,链接id:{}",ctx.channel().id().asLongText());
                ctx.channel().close();
            }
        }
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        log.error("连接异常：{}",cause.getMessage());
        super.exceptionCaught(ctx, cause);
        Channel channel = ctx.channel();
        if(channel.isActive()){
            ctx.channel().writeAndFlush("server exception");
            ctx.close();
        }
        // 删除通道
//        NettyConfig.getChannelGroup().remove(ctx.channel());
//        removeUserId(ctx);
        ctx.close();
    }

    /**
     * 删除用户与channel的对应关系
     * @param ctx
     */
    private void removeUserId(ChannelHandlerContext ctx){
        AttributeKey<String> key = AttributeKey.valueOf("userId");
        String userId = ctx.channel().attr(key).get();
        if(StringUtil.isNotEmpty(userId)) {
            NettyConfig.getUserChannelMap().remove(userId);
        }

    }
}
